package byteBuddy;


import lombok.extern.slf4j.Slf4j;
import net.bytebuddy.implementation.bind.annotation.*;

import java.lang.reflect.Method;

@Slf4j
public class MyInterceptorWithMorph {

    private MethodInterceptor methodInterceptor;

    public MyInterceptorWithMorph(MethodInterceptor methodInterceptor) {
        this.methodInterceptor = methodInterceptor;
    }

    @RuntimeType
    public Object intercept(@This(optional = true) Object obj, @AllArguments Object[] allArguments,
                            @Origin Method method, @Morph Morphing<?> callable, @Origin Class<?> clazz) throws Exception {
        try {
            methodInterceptor.beforeExecute(clazz, obj, method, allArguments);
        } catch (Throwable ignored) {
            log.warn(ignored.getMessage(), ignored);
        }
        Object ret = null;
        try {
            ret = callable.morph(allArguments);
        } catch (Throwable throwable) {
            try {
                methodInterceptor.onException(clazz, obj, method, allArguments, throwable);
            } catch (Throwable ignored) {
                log.warn(ignored.getMessage(), ignored);
            }
            throw throwable;
        } finally {
            try{
                ret = methodInterceptor.onComplete(clazz, obj, method, allArguments, ret);
            }catch (Throwable ignored){
                log.warn(ignored.getMessage(), ignored);
            }
        }
        return ret;
    }

}
